package web.servlet;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import domain.*;
import service.UserService;
import service.impl.UserServiceImpl;
import org.apache.commons.beanutils.BeanUtils;
import util.Md5Util;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;


@WebServlet("/user/*")
public class UserServlet extends BaseServlet {
    private UserService service = new UserServiceImpl();

    /**
     * 用户登录
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //验证校验
        String check = request.getParameter("check");
        System.out.println("表单验证码：" + check + "----RegistUserServlet----doPost");
        //从sesion中获取验证码
        HttpSession session = request.getSession();
//        String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");
        String checkcode_server = CheckCode.getCheckCode();
        System.out.println("获取后台验证码：" + checkcode_server + "----RegistUserServlet----doPost");
        session.removeAttribute("CHECKCODE_SERVER");//为了保证验证码只能使用一次
        //比较
        if (checkcode_server == null || !checkcode_server.equalsIgnoreCase(check)) {
            //验证码错误
            ResultInfo info = new ResultInfo();
            //注册失败
            info.setFlag(false);
            info.setErrorMsg("验证码错误");
            //将info对象序列化为json
            //调用父类方法
            writeValue(info, response);
            return;
        }
        Map<String, String[]> map = request.getParameterMap();
        User user = new User();
        try {
            BeanUtils.populate(user, map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        String createTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        boolean flag = service.regist(user, createTime);
        ResultInfo info = new ResultInfo();
        //4.响应结果
        if (flag) {
            //注册成功
            info.setFlag(true);
            System.out.println("注册成功！--registUserServlet");
        } else {
            //注册失败
            info.setFlag(false);
            info.setErrorMsg("注册失败,用户名已存在！");
        }
        writeValue(info, response);
    }

    /**
     * 用户邮箱激活
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void active(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String code = request.getParameter("code"); //来自UserServiceImpl类
        if (code != null) {
            boolean flag = service.active(code);
            String msg = null;
            if (flag) {
                //激活成功
                response.sendRedirect(request.getContextPath() + "/active_ok.html");
            } else {
                //激活失败
                msg = "激活失败，请联系管理员！";
                // 设置响应内容类型为HTML
                response.setContentType("text/html;charset=UTF-8");
                // 获取PrintWriter对象
                PrintWriter out = response.getWriter();
                // 输出HTML代码
                out.println("<!DOCTYPE html>");
                out.println("<html>");
                out.println("<head>");
                out.println("<title>激活结果</title>");
                out.println("</head>");
                out.println("<body>");
                out.println("<h1>" + msg + "</h1>");
                out.println("</body>");
                out.println("</html>");
                // 关闭PrintWriter对象
                out.close();
            }
        }
    }


    /**
     * 用户登录
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取用户名和密码数据
        Map<String, String[]> map = request.getParameterMap();
        //2.封装User对象
        User user = new User();
        try {
            BeanUtils.populate(user, map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        User u = service.login(user);
        ResultInfo info = new ResultInfo();
        System.out.println(u);
        //4.判断用户对象是否为null
        if (u == null) {
            //用户名密码或错误
            info.setFlag(false);
            info.setErrorMsg("用户名密码或错误!");
        }
        //5.判断用户是否激活
        if (u != null && !"Y".equals(u.getStatus())) {
            //用户尚未激活
            info.setFlag(false);
            info.setErrorMsg("您尚未激活，请激活!");
        }
        //6.判断登录成功
        if (u != null && "Y".equals(u.getStatus())) {
            request.getSession().setAttribute("user", u);//登录成功标记
            info.setFlag(true);
        }
        //响应数据
        //用于判断是否登录,返回数据为空则为没有登录成功
        writeValue(info, response);
    }

    /**
     * 判断用户是否登录
     *
     * @param request
     * @param response
     */
    public void loginOrNot(HttpServletRequest request, HttpServletResponse response) {
        User user = (User) request.getSession().getAttribute("user");
        try {
            writeValue(user, response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 查找单个用户对象
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void findOneByCode(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        User user = (User) request.getSession().getAttribute("user");
        System.out.println(user + "----------->findOneByCode");
        User u = service.findOneByCode(user.getCode());
        //将user写回客户端
        writeValue(u, response);//这是什么
    }

    /**
     * 查询用户文章数量
     *
     * @param request
     * @param response
     */
    public void findArticleNumByCode(HttpServletRequest request, HttpServletResponse response) {
        User user = (User) request.getSession().getAttribute("user");
        int num = service.findArticleNumByCode(user.getCode());
        try {
            writeValue(num, response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 退出登录
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void exit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.销毁session
        request.getSession().invalidate();
        //2.跳转登录页面
        response.sendRedirect(request.getContextPath() + "/login.html");
    }


    /**
     * 更新用户头像
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void updateImage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取请求体中的JSON数据
        BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
        StringBuilder jsonBody = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            jsonBody.append(line);
        }
        reader.close();
        // 解析JSON数据为JsonObject
        JsonObject jsonData = new Gson().fromJson(jsonBody.toString(), JsonObject.class);
        // 从JsonObject中提取数据
        String image = jsonData.get("avatarName").getAsString();

        // 在这里处理接收到的数据
        // image 是从JSON数据中提取的头像名称值

        System.out.println("头像名称：" + image);
        User userAgo = (User) request.getSession().getAttribute("user");
        service.updateImage(userAgo.getCode(), image);
        //重新更新session域中的user
        User userNow = service.findOneByCode(userAgo.getCode());
        request.getSession().setAttribute("user", userNow);
        // 返回响应
        response.setStatus(HttpServletResponse.SC_OK);
    }


    public void findImage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        User user = (User) request.getSession().getAttribute("user");
        User userNow = service.findOneByCode(user.getCode());
        request.getSession().setAttribute("user", userNow);
        writeValue(userNow, response);
    }

    /**
     * 更新用户昵称
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void updateNickName(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        String nickname = request.getParameter("nickname");
        System.out.println("接受的数据: " + nickname);
        User userAgo = (User) request.getSession().getAttribute("user");
        //更新昵称并返回数据库受影响的行数
        int row = service.updateNickNameByCode(userAgo.getCode(), nickname);
        //重新更新session中的user
        User userNow = service.findOneByCode(userAgo.getCode());
        request.getSession().setAttribute("user", userNow);
        System.out.println("userAgo:" + userAgo);
        System.out.println("userNow:" + userNow);
        if (row != 0) {
            // 返回上传成功的信息给前端
            response.getWriter().println("修改成功");
        } else {
            response.getWriter().println("修改失败！");
        }

    }


    /**
     * 更新用户密码
     *
     * @param request
     * @param response
     */
    public void updatePassword(HttpServletRequest request, HttpServletResponse response) throws Exception {
        User userAgo = (User) request.getSession().getAttribute("user");
        String oldPassword = request.getParameter("oldPassword");
        String newPassword = request.getParameter("newPassword");
        System.out.println("旧密码" + oldPassword);
        System.out.println("新密码" + newPassword);
        //比较输入的旧密码和数据库中的是否一样
        User u = service.findOneByCode(userAgo.getCode());
        ResultInfo info = new ResultInfo();
        if (u.getPassword().equals(oldPassword)) {
            //前后端的密码相同，更改密码
            int row = service.updatePasswordByCode(userAgo.getCode(), Md5Util.encodeByMd5(newPassword));
            if (row != 0) {
                //修改成功
                User userNow = service.findOneByCode(u.getCode());
                //更行session中的user
                request.getSession().setAttribute("user", userNow);
                //提示用户修改成功
                info.setFlag(false);
                info.setErrorMsg("修改成功！");
                try {
                    writeValue(info, response);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            } else {
                //修改失败
                info.setFlag(false);
                info.setErrorMsg("修改失败,请稍后再试！");
                try {
                    writeValue(info, response);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

        } else {
            info.setFlag(false);
            info.setErrorMsg("原密码输入错误,请重新输入！");
            try {
                writeValue(info, response);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }


    /**
     * 发布文章
     *
     * @param request
     * @param response
     */
    public void publishArticle(HttpServletRequest request, HttpServletResponse response) {

        User user = (User) request.getSession().getAttribute("user");
        String title = request.getParameter("title");
        int cid = Integer.parseInt(request.getParameter("category"));
        if (cid == 0) {
            cid = 1;
        }
        String[] tags = request.getParameterValues("tags");
        String visible = request.getParameter("visible");
        System.out.println("标签：" + tags.toString());
        System.out.println("标题：" + title);
        String text = request.getParameter("content");
        String createTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());

        //把文章的数据存入到文章表中,并返回这个对象
        Article article = service.setArticle(cid, visible, title, text, createTime, user.getCode());
        System.out.println(article + "--------------------->user/publishArticle");
        //设置文章标签
        service.setLabel(article.getCode(), article.getRid(), tags);

        if (article != null) {
            try {
                response.getWriter().println("发布成功！");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } else {
            try {
                response.getWriter().println("发布失败！");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }


    public void pageQuery(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取参数
        String currentPage = request.getParameter("currentPage");//当前页数
        String rows = request.getParameter("rows");//每页显示条数
        User user = (User) request.getSession().getAttribute("user");
        if (currentPage == null || "".equals(currentPage)) {
            currentPage = "1";
        }
        if (rows == null || "".equals(rows)) {
            rows = "5";
        }
        PageBean pb = service.findArticleByPage(currentPage, rows, user.getCode());
        System.out.println(pb + "---------------->user/pageQuery");
        //3.将pageBean存到request
        request.setAttribute("pb", pb);
        //4.转发到list.jsp
        request.getRequestDispatcher("/deleteArticle.jsp").forward(request, response);
    }


    public void deleteArticle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String rid = request.getParameter("rid");
        service.deleteArticle(Integer.parseInt(rid));
        response.sendRedirect(request.getContextPath() + "/user/pageQuery");
    }

    public void deleteSelected(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        String[] Rds = request.getParameterValues("rid");
        UserService service = new UserServiceImpl();
        service.delSelectedArticleById(Rds);
        response.sendRedirect(request.getContextPath() + "/user/pageQuery");
    }

    public void findArticle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String rid = request.getParameter("rid");
        Article article = service.findArticleByRid(Integer.parseInt(rid));
        System.out.println(article + "----------->user/findArticle");
        request.getSession().setAttribute("article", article);
        request.getSession().removeAttribute("errorMsg");
        request.getRequestDispatcher("/editArticle.jsp").forward(request, response);
    }

    public void updateArticle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String rid = request.getParameter("rid");
        String title = request.getParameter("title");
        String text = request.getParameter("text");
        String visible = request.getParameter("visibility");
        String modifyTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        service.updateArticle(Integer.parseInt(rid), title, text, modifyTime, visible);
        Article article = service.findArticleByRid(Integer.parseInt(rid));
        System.out.println(article + "----------->user/findArticle");
        request.getSession().setAttribute("article", article);
        request.setAttribute("errorMsg", "修改成功！");
        request.getRequestDispatcher("/editArticle.jsp").forward(request, response);
    }

    public void findArticleFromRecycle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        User user = (User) request.getSession().getAttribute("user");
        String currentPage = request.getParameter("currentPage");
        String rows = request.getParameter("rows");
        if (currentPage == null || "".equals(currentPage)) {
            currentPage = "1";
        }
        if (rows == null || "".equals(rows)) {
            rows = "10";
        }
        PageBean pb = service.findArticleByPageFromRecycle(currentPage, rows, user.getCode());
        System.out.println(pb + "---------------->user/deleteArticleFromRecycle");
        request.setAttribute("pb", pb);
        request.getRequestDispatcher("/recycle.jsp").forward(request, response);
    }

    public void deleteArticleFromRecycle(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String rid = request.getParameter("rid");
        User user = (User) request.getSession().getAttribute("user");
        service.deleteArticleFromRecycle(Integer.parseInt(rid));
        response.sendRedirect(request.getContextPath() + "/user/findArticleFromRecycle");
    }

    public void deleteSelectedArticleFromRecycle(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String[] Rds = request.getParameterValues("rid");
        UserService service = new UserServiceImpl();
        service.delSelectedArticleFromRecycle(Rds);
        response.sendRedirect(request.getContextPath() + "/user/findArticleFromRecycle");
    }

    public void giveLike(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        User user = (User) request.getSession().getAttribute("user");
        if (user != null) {
            String rid = request.getParameter("rid");
            try {
                Favour favour = service.findLikeOrNot(user.getCode(), Integer.parseInt(rid));
                if (favour == null || favour.equals("")) {
                    service.addFavour(user.getCode(), Integer.parseInt(rid));
                    Article favourNum = service.findArticleByRid(Integer.parseInt(rid));
                    request.getSession().setAttribute("message", "已赞");
                    request.getSession().setAttribute("article", favourNum);
                } else {
                    request.getSession().setAttribute("message", "请勿重复点赞");
                }
            } catch (NumberFormatException e) {
                System.out.println("这篇文章未被点赞,rid:" + rid + "---------->user/giveLike");
            }
            request.getRequestDispatcher("/articleShow.jsp").forward(request, response);
        } else {
            request.getSession().setAttribute("message", "请登录后点赞！");
            request.getRequestDispatcher("/articleShow.jsp").forward(request, response);
        }
    }


    public void recoverArticle(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String rid = request.getParameter("rid");
        service.recoverArticleByRid(Integer.parseInt(rid));
        response.sendRedirect(request.getContextPath() + "/user/findArticleFromRecycle");
    }

}
